package com.dobby.htmlunit.demo.jianshu;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlSpan;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 使用 htmlunit
 * Created by jonas on 2016/12/24.
 */
public class JianshuPoster {

    private static WebClient webClient = null;

    private String cookie = null;

    private JianshuPoster() {
    }

    private JianshuPoster(String cookie) {
        this.cookie = cookie;
    }

    private static WebClient getWebClient() {
        if(webClient == null) {
            webClient = new WebClient();
            webClient.getOptions().setCssEnabled(false);
            webClient.getOptions().setJavaScriptEnabled(true);
            webClient.getOptions().setRedirectEnabled(true);
            webClient.setAjaxController(new NicelyResynchronizingAjaxController());
            webClient.getCookieManager().setCookiesEnabled(true);
            webClient.getOptions().setThrowExceptionOnScriptError(false);
            webClient.waitForBackgroundJavaScript(10000);
            webClient.getOptions().setTimeout(10000);
        }
        return webClient;
    }

    public static JianshuPoster addCookie(String cookie) {
        if(StringUtils.isNotBlank(cookie)) {
            return new JianshuPoster(cookie);
        }
        return new JianshuPoster();
    }

    private WebRequest addHeaders(WebRequest request) throws Exception {
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Accept","application/json, text/javascript, */*; q=0.01");
        headers.put("Accept-Encoding","gzip, deflate, sdch");
        headers.put("Accept-Language","zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4");
        headers.put("Connection","keep-alive");
        headers.put("Content-Type","application/json; charset=utf-8");
        headers.put("Host","www.jianshu.com");
//        headers.put("Origin","http://www.jianshu.com");
//        headers.put("Referer","http://www.jianshu.com/writer");
        headers.put("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36");
//        headers.put("X-CSRF-Token","myWbeFVhJd6bPKeOxvEuxE1zbtOEpZFn9MjxuvChhUCQHxcFOeMV+cKza5VN1aTUltRL+glR/KeFVO+bGhTlNA==");
        headers.put("X-Requested-With","XMLHttpRequest");
        if(null != this.cookie) {
            headers.put("cookie", this.cookie);
        } else {
            throw new Exception("缺少cookie信息");
        }
        request.setAdditionalHeaders(headers);
        return request;
    }


    /**
     * 新建笔记
     * @return
     * @throws IOException
     */
    private String newNote() throws Exception {
       return newNote(null);
    }


    /**
     * 在一个笔记本里面新建一个笔记
     * @param notebookId  可传可不传，不传就取默认的第一个笔记本
     * @throws IOException
     */
    private String newNote(Integer notebookId) throws Exception {
        String url = "http://www.jianshu.com/writer/notes";
        WebRequest request = new WebRequest(new URL(url), HttpMethod.POST);
        addHeaders(request);
        // 添加请求参数
        JSONObject jsonObject = new JSONObject();
        if(notebookId == null) {
            notebookId = getDefaultNotebookId(getAllNotebooks());
        }
        jsonObject.put("notebook_id", notebookId);  // 指定某个笔记本
        request.setRequestBody(jsonObject.toJSONString());
        Page page = getWebClient().getPage(request);

        WebResponse webResponse = page.getWebResponse();
        String jsonInfo = webResponse.getContentAsString();
        System.out.println("new note =====> " + jsonInfo);
        return jsonInfo;
    }


    /**
     * 更新笔记
     * @param noteId
     * @return 笔记的json信息
     */
    private String updateNote(Integer noteId, String title, String content) throws Exception {
        String url = "http://www.jianshu.com/writer/notes/" + noteId;

        WebRequest request = new WebRequest(new URL(url));
        request.setHttpMethod(HttpMethod.PUT);
        request.setCharset("UTF-8");
        addHeaders(request);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("title", title);
        jsonObject.put("content", content);

        String noteInfo = getNoteInfo(noteId);
        Integer autosave_control = ((JSONObject) JSON.parse(noteInfo)).getInteger("autosave_control");
        jsonObject.put("autosave_control", autosave_control + 1);   // 版本号，每次修改都要比上一次数值大

        request.setRequestBody(jsonObject.toJSONString());
        Page page = getWebClient().getPage(request);

        WebResponse webResponse = page.getWebResponse();
        String jsonInfo = webResponse.getContentAsString();
        System.out.println("update note =====> " + jsonInfo);
        return jsonInfo;
    }


    /**
     * 发布笔记
     * 新建笔记之后，发布出去
     * @throws IOException
     */
    private String publishNote(Integer noteId) throws Exception {
        String url = "http://www.jianshu.com/writer/notes/" + noteId + "/publicize";

        WebRequest request = new WebRequest(new URL(url));
        request.setHttpMethod(HttpMethod.POST);
        request.setCharset("UTF-8");
        addHeaders(request);
        Page page = getWebClient().getPage(request);

        WebResponse webResponse = page.getWebResponse();
        String jsonInfo = webResponse.getContentAsString();
        System.out.println("publish note =====> " + jsonInfo);
        return jsonInfo;
    }


    /**
     *  编译笔记
     *  修改笔记之后的编译更新，相当于重新发布
     * @param noteId
     * @throws IOException
     */
    private String compileNote(Integer noteId) throws Exception {
        String url = "http://www.jianshu.com/writer/notes/" + noteId + "/compile";

        WebRequest request = new WebRequest(new URL(url));
        request.setHttpMethod(HttpMethod.POST);
        request.setCharset("UTF-8");
        addHeaders(request);
        Page page = getWebClient().getPage(request);

        WebResponse webResponse = page.getWebResponse();
        String jsonInfo = webResponse.getContentAsString();
        System.out.println("compile note =====> " + jsonInfo);
        return jsonInfo;
    }



    /**
     * 获取所有的笔记本信息
     * @return
     */
    public String getAllNotebooks() throws Exception {
        String url = "http://www.jianshu.com/writer/notebooks";

        WebRequest request = new WebRequest(new URL(url), HttpMethod.GET);
        addHeaders(request);
        Page page = getWebClient().getPage(request);

        WebResponse webResponse = page.getWebResponse();
        String jsonInfo = webResponse.getContentAsString();

        JSONArray jsonArray = (JSONArray) JSON.parse(jsonInfo);
        // 过滤已经删除的笔记本
        for(Iterator iterator = jsonArray.iterator(); iterator.hasNext(); ) {
            JSONObject jo = (JSONObject) iterator.next();
            if(jo.get("deleted_at") != null) {
                iterator.remove();
            }
        }
        return jsonArray.toJSONString();

    }


    /**
     * 获取默认的笔记本id
     * @return
     */
    private Integer getDefaultNotebookId(String notebooks) {
        JSONArray jsonArray = (JSONArray) JSON.parse(notebooks);
        if(null == jsonArray) {
            return null;
        }
        JSONObject jsonObject = (JSONObject) jsonArray.get(0);
        Integer notebookId = (Integer)jsonObject.get("id");
        return notebookId;
    }


    /**
     * 获取笔记的信息
     * @param noteId
     * @return
     * @throws IOException
     */
    public String getNoteInfo(Integer noteId) throws Exception {
        String url = "http://www.jianshu.com/writer/notes/" + noteId;

        WebRequest request = new WebRequest(new URL(url));
        request.setHttpMethod(HttpMethod.PUT);
        request.setCharset("UTF-8");
        addHeaders(request);
        Page page = getWebClient().getPage(request);
        WebResponse webResponse = page.getWebResponse();
        String jsonInfo = webResponse.getContentAsString();

        JSONObject jsonObject = (JSONObject) JSON.parse(jsonInfo);
        String link = (String) jsonObject.get("slug");
        String accessUrl = "http://www.jianshu.com/p/" + link;
        jsonObject.put("accessUrl", accessUrl);
        String newNoteInfo = jsonObject.toJSONString();
        System.out.println("note info =====> " + newNoteInfo);
        return newNoteInfo;
    }



    /**
     * 删除笔记
     * @throws Exception
     */
    public String deleteNote(Integer noteId) throws Exception {
        String url = "http://www.jianshu.com/writer/notes/" + noteId + "/soft_destroy";

        WebRequest request = new WebRequest(new URL(url));
        request.setHttpMethod(HttpMethod.POST);
        addHeaders(request);
        Page page = getWebClient().getPage(request);

        String jsonInfo = page.getWebResponse().getContentAsString();
        System.out.println("delete note =====> " + jsonInfo);
        return jsonInfo;
    }


    /**
     * 获取笔记的内容
     */
    public String getNoteContent(Integer noteId) throws Exception {
        String url = "http://www.jianshu.com/writer/notes/" + noteId + "/content";

        WebRequest request = new WebRequest(new URL(url));
        request.setHttpMethod(HttpMethod.GET);
        request.setCharset("UTF-8");
        addHeaders(request);
        Page page = getWebClient().getPage(request);

        WebResponse webResponse = page.getWebResponse();
        String jsonInfo = webResponse.getContentAsString();
        System.out.println("note content =====> " + jsonInfo);
        return jsonInfo;
    }


    /**
     * 查询所有笔记列表
     * @throws IOException
     */
    public String getAllNotes() throws Exception {
        String url = "http://www.jianshu.com/writer/notes";

        WebRequest request = new WebRequest(new URL(url));
        request.setHttpMethod(HttpMethod.GET);
        addHeaders(request);
        Page page = getWebClient().getPage(request);

        WebResponse webResponse = page.getWebResponse();
        String jsonInfo = webResponse.getContentAsString();
        JSONArray jsonArray = (JSONArray) JSON.parse(jsonInfo);
        // 过滤已经删除的笔记本
        for(Iterator iterator = jsonArray.iterator(); iterator.hasNext(); ) {
            JSONObject jo = (JSONObject) iterator.next();
            if(jo.get("deleted_at") != null) {
                iterator.remove();
            }
        }
        return jsonArray.toJSONString();
    }


    /**
     * 新建一个笔记，然后添加内容，最后发布
     * @return
     */
    public String newNoteThenPublish(String title, String content) throws Exception {
        System.out.println("============================= 同步简书 新建笔记 ========================================");
        String noteInfo = newNote();
        Integer noteId = ((JSONObject) JSON.parse(noteInfo)).getInteger("id");
        updateNote(noteId, title, content);
        publishNote(noteId);
        return getNoteInfo(noteId);
    }


    /**
     * 修改一个笔记的内容，然后发布
     * @return
     */
    public String updateNoteThenCompile(Integer noteId, String title, String content) throws Exception {
        System.out.println("============================= 同步简书 修改笔记 ========================================");
        updateNote(noteId,title, content);
        compileNote(noteId);
        return getNoteInfo(noteId);
    }


    /**
     * 获取笔记的统计信息（阅读数、点赞数、评论数）
     * @return
     */
    public String getNoteStatInfo(Integer noteId) throws Exception {
        System.out.println("============================= 获取简书 统计信息  ========================================");
        Integer likesCount = 0;
        Integer viewsCount = 0;
        Integer commentsCount = 0;

        String noteInfo = getNoteInfo(noteId);
        String url = ((String) ((JSONObject) JSON.parse(noteInfo)).get("accessUrl"));
        HtmlPage resultPage = null;
        try {
            WebRequest webRequest = new WebRequest(new URL(url));
            resultPage = getWebClient().getPage(webRequest);
        } catch (IOException e) {
            e.printStackTrace();
        }

        List<HtmlSpan> spanElements = (List<HtmlSpan>) resultPage.getByXPath("//div[@class='article']/div[@class='author']/div[@class='info']//div[@class='meta']/span");
        for(HtmlSpan hs : spanElements) {
            String textContent = hs.asText();
            if(StringUtils.contains(textContent, "喜欢")) {
                String count = StringUtils.remove(textContent, "喜欢");
                likesCount =  Integer.valueOf(StringUtils.trim(count));
            } else if(StringUtils.contains(textContent, "评论")) {
                String count = StringUtils.remove(textContent, "评论");
                commentsCount =  Integer.valueOf(StringUtils.trim(count));
            } else if(StringUtils.contains(textContent, "阅读")) {
                String count = StringUtils.remove(textContent, "阅读");
                viewsCount =  Integer.valueOf(StringUtils.trim(count));
            }
        }

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("likesCount", likesCount);
        jsonObject.put("viewsCount", viewsCount);
        jsonObject.put("commentsCount", commentsCount);
        String statInfo = jsonObject.toJSONString();
        System.out.println("note stat info ============ >" + statInfo);
        return statInfo;
    }



    /**
     * 获取笔记的评论
     * @return
     */
    public String getNoteComments(Integer noteId) throws Exception {
        String url = "http://www.jianshu.com/notes/" + noteId+ "/comments";
        WebRequest webRequest = null;
        Page page = null;

        webRequest = new WebRequest(new URL(url), HttpMethod.GET);
        addHeaders(webRequest);
        page = getWebClient().getPage(webRequest);

        String jsonInfo = page.getWebResponse().getContentAsString();
        JSONArray jsonArray = (JSONArray) ((JSONObject) JSON.parse(jsonInfo)).get("comments");
        return jsonArray.toJSONString();
    }


    /**
     * 获取用户的信息
     * @return
     * @throws Exception
     */
    public String getUserInfo() throws Exception {
        String url = "http://www.jianshu.com/settings/basic";
        WebRequest webRequest = new WebRequest(new URL(url), HttpMethod.GET);
        addHeaders(webRequest);
        Page page = getWebClient().getPage(webRequest);
        String jsonInfo = page.getWebResponse().getContentAsString();
        System.out.println("============================================> 简书获取到的用户信息：" + jsonInfo);
        return jsonInfo;
    }


    /**
     * 判断是否绑定手机
     * @return
     * @throws Exception
     */
    public boolean isBindMobile() throws Exception {
        String userInfo = getUserInfo();
        JSONObject jsonObject = (JSONObject) JSONArray.parse(userInfo);
        JSONObject data = (JSONObject) (jsonObject.get("data"));
        String mobile_number = (String) data.get("mobile_number");
        System.out.println("============================================> 简书获取到的用户手机号为：" + mobile_number);
        if(StringUtils.isNotBlank(mobile_number)) {
            return true;
        } else {
            return false;
        }
    }
}
